package de.tum.in.eist.poll.server;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

import de.tum.in.eist.poll.shared.Feedback;
import de.tum.in.eist.poll.shared.Lecture;
import de.tum.in.eist.poll.shared.Lecturer;
import de.tum.in.eist.poll.shared.Student;
import de.tum.in.eist.poll.shared.User;

public class CSVDatabase {

	public static final String HOME = System.getProperty("user.home")
			+ File.separator + "EIST_POLL_24" + File.separator;

	CSVDatabase() {

	}

	/**
	 * Fetch feedback of a specific lecture
	 * 
	 * @param l
	 *            The lecture to check for
	 * @return The Feedback stored
	 * @throws IOException
	 */
	public static List<Feedback> fetchFeedback(Lecture l) throws IOException {
		List<Feedback> feedback = new LinkedList<Feedback>();
		
		File x = new File(HOME);
		if(!x.exists()) {
			x.mkdirs();
		}

		BufferedReader reader = new BufferedReader(new FileReader(HOME
				+ "Feedbacks.dtb"));
		while (true) {
			String line = reader.readLine();
			if (line == null)
				break;
			String[] tokens = line.split(";");
			if (tokens == null || tokens.length < 4)
				continue;

			if (tokens[0].equals(l.getLectureID())) {
				Feedback f = new Feedback(l, null, Integer.parseInt(tokens[1]),
						tokens[2].replaceAll("&arsch", ";"),
						tokens[3].replaceAll("&arsch", ";"));
				feedback.add(f);
			}

		}
		reader.close();
		return feedback;
	}

	/**
	 * Store feedback to the database
	 * 
	 * @param feedback
	 *            the feedback to store
	 * @throws IOException
	 */
	public static void storeFeedback(Feedback feedback) throws IOException {
		if(feedback == null)
			return;

		File x = new File(HOME);
		if(!x.exists()) {
			x.mkdirs();
		}
		
		BufferedWriter writer = new BufferedWriter(new FileWriter(HOME
				+ "Feedbacks.dtb", true));

		String like = feedback.getLike().replaceAll(";", "&arsch")+" ";
		String dislike = feedback.getDisLike().replaceAll(";", "&arsch")+" ";

		writer.write(feedback.getLecture().getLectureID() + ";"
				+ feedback.getSatisfaction() + ";" + like + ";" + dislike
				+ "\n");

		writer.flush();
		writer.close();
	}

	/**
	 * Get all lectures stored in the database
	 * 
	 * @return the lectures
	 * @throws IOException
	 */
	public static List<Lecture> fetchLectures() throws IOException {
		File x = new File(HOME);
		if(!x.exists()) {
			x.mkdirs();
		}
		
		List<Lecture> lectures = new LinkedList<Lecture>();

		BufferedReader reader = new BufferedReader(new FileReader(HOME
				+ "Lectures.dtb"));
		while (true) {
			String line = reader.readLine();
			if (line == null)
				break;
			String[] tokens = line.split(";");
			if (tokens.length < 4)
				throw new IOException();
			Lecture l = new Lecture(tokens[0], tokens[1],
					(Lecturer) findUser(tokens[2]), tokens[3].matches("true"));
			if (tokens.length > 4) {
				String[] studentTokens = tokens[4].split(",");
				for (String s : studentTokens) {
					s = s.replaceAll("&arsch", ";");
					s = s.replaceAll("&dumm", ",");
					l.addStudent((Student) findUser(s));
				}
			}
			lectures.add(l);
		}
		reader.close();
		return lectures;
	}

	/**
	 * Get lecture with specific id
	 * 
	 * @param id
	 *            the lecture id
	 * @return The lecture otherwise null
	 * @throws IOException
	 */
	public static Lecture fetchLecture(String id) throws IOException {
		File x = new File(HOME);
		if(!x.exists()) {
			x.mkdirs();
		}
		
		Lecture lecture = null;

		BufferedReader reader = new BufferedReader(new FileReader(HOME
				+ "Lectures.dtb"));
		while (true) {
			String line = reader.readLine();
			if (line == null)
				break;
			String[] tokens = line.split(";");
			if (tokens.length < 4)
				throw new IOException();

			if (tokens[0].equals(id)) {
				lecture = new Lecture(tokens[0], tokens[1],
						(Lecturer) findUser(tokens[2]),
						tokens[3].matches("true"));
				if (tokens.length > 4) {
					String[] studentTokens = tokens[4].split(",");
					for (String s : studentTokens) {
						s = s.replaceAll("&arsch", ";");
						s = s.replaceAll("&dumm", ",");
						lecture.addStudent((Student) findUser(s));
					}
				}
				break;
			}
		}
		reader.close();
		return lecture;
	}

	/**
	 * adds a student ident to a lecture indication that he already rated this
	 * lecture and sets the lecture status to updated
	 * 
	 * @param lectureID
	 *            the lecture id
	 * @param student
	 *            the student
	 */
	public static void addRatedStudentToLecture(String lectureID,
			Student student) {
		File x = new File(HOME);
		if(!x.exists()) {
			x.mkdirs();
		}
		
		try {
			List<Lecture> lectures = fetchLectures();
			Iterator<Lecture> it = lectures.iterator();
			boolean first = true;
			while (it.hasNext()) {
				Lecture l = it.next();
				if (l.getLectureID().equals(lectureID)) {
					l.addStudent(student);
					l.setUpdated(true);
				}
				storeLecture(l, first);
				first = false;
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	/**
	 * Removes the update status of a lecture
	 * 
	 * @param lectureID
	 *            the lecture that is not updated anymore
	 */
	public static void removeUpdatedFromLecture(String lectureID) {
		File x = new File(HOME);
		if(!x.exists()) {
			x.mkdirs();
		}
		
		try {
			List<Lecture> lectures = fetchLectures();
			Iterator<Lecture> it = lectures.iterator();
			boolean first = true;
			while (it.hasNext()) {
				Lecture l = it.next();
				if (l.getLectureID().equals(lectureID)) {
					l.setUpdated(false);
				}
				storeLecture(l, first);
				first = false;
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	/**
	 * Stores a lecture in the database
	 * 
	 * @param l
	 *            the lecture
	 * @param override
	 *            if true database is cleared and overridden
	 * @throws IOException
	 */
	public static void storeLecture(Lecture l, boolean override)
			throws IOException {
		File x = new File(HOME);
		if(!x.exists()) {
			x.mkdirs();
		}
		
		BufferedWriter writer = new BufferedWriter(new FileWriter(HOME
				+ "Lectures.dtb", !override));

		String students = "";
		Iterator<Student> it = l.getStudents().iterator();
		while (it.hasNext()) {
			if (!students.isEmpty())
				students += ",";
			Student s = it.next();

			String newStudent = s.getName().replaceAll(";", "&arsch");
			newStudent = newStudent.replaceAll(",", "&dumm");

			students += newStudent;
		}

		writer.write(l.getLectureID() + ";" + l.getLectureTitle() + ";"
				+ l.getLecturer().getName() + ";"
				+ (l.isUpdated() ? "true" : "false") + ";" + students + "\n");
		writer.flush();
		writer.close();
	}

	/**
	 * finds a user in the database
	 * 
	 * @param name
	 *            username
	 * @return the user otherwise null
	 * @throws IOException
	 */
	public static User findUser(String name) throws IOException {
		File x = new File(HOME);
		if(!x.exists()) {
			x.mkdirs();
		}
		
		BufferedReader reader = new BufferedReader(new FileReader(HOME
				+ "Users.dtb"));
		while (true) {
			String line = reader.readLine();
			if (line == null)
				break;
			String[] tokens = line.split(";");
			if (tokens.length < 3)
				throw new IOException();
			if (tokens[0].equals(name)) {
				reader.close();
				if (tokens[2].equalsIgnoreCase("student"))
					return new Student(name, tokens[1]);
				else
					return new Lecturer(name, tokens[1]);
			}
		}
		reader.close();
		return null;
	}

	/**
	 * Store a new user in the database
	 * 
	 * @param user
	 *            the user to store
	 * @throws IOException
	 */
	public static void storeUser(User user) throws IOException {
		File x = new File(HOME);
		if(!x.exists()) {
			x.mkdirs();
		}
		
		BufferedWriter writer = new BufferedWriter(new FileWriter(HOME
				+ "Users.dtb", true));
		writer.write(user.getName() + ";" + user.getPassword() + ";"
				+ (user instanceof Student ? "student" : "lectuerer") + "\n");
		writer.flush();
		writer.close();
	}

	/**
	 * adds feedback to a lecture
	 * 
	 * @param lecture
	 *            the lecture that is rated
	 * @param feedback
	 *            the feedback
	 */
	public static void addFeedbackToLecture(Lecture lecture, Feedback feedback) {
		if(lecture == null || feedback ==null)
			return;
		File x = new File(HOME);
		if(!x.exists()) {
			x.mkdirs();
		}
		
		try {
			CSVDatabase.storeFeedback(feedback);
			CSVDatabase.addRatedStudentToLecture(lecture.getLectureID(),
					feedback.getStudent());
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	/**
	 * checks if name/password is a valid combination
	 * 
	 * @param name
	 *            the namse
	 * @param password
	 *            the password
	 * @return true if it is valid
	 */
	public static boolean isValidInput(String name, String password) {
		try {
			User u = findUser(name);
			if (u != null && u.getPassword().equals(password))
				return true;
		} catch (IOException e) {
			try {
				storeUser(new Student("Student_1", "new"));
				storeUser(new Student("Student_2", "new"));
				storeUser(new Lecturer("Prof", "new"));
				storeUser(new Lecturer("Maalej", "new"));
			} catch (IOException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
			e.printStackTrace();
		}

		return false;
	}

	/**
	 * gets a user by name from the database
	 * 
	 * @param name
	 *            The namse of the user
	 * @return the user or null
	 */
	public static User getUser(String name) {
		try {
			return findUser(name);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * get all lectures from the database
	 * 
	 * @return the lectures
	 */
	public static List<Lecture> getLectures() {
		try {
			return fetchLectures();
		} catch (IOException e) {
			try {
				storeLecture(new Lecture("IN001", "EIST_1", new Lecturer("Prof", "new"), false), false);
				storeLecture(new Lecture("IN002", "EIST_2", new Lecturer("Prof", "new"), false), false);
				storeLecture(new Lecture("IN003", "EIST_3", new Lecturer("Maalej", "new"), false), false);
			} catch (IOException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
			e.printStackTrace();
		}
		return new LinkedList<Lecture>();
	}

	/**
	 * Get lecture with specific id
	 * 
	 * @param lectureID
	 *            the lecture id
	 * @return the lectureor null
	 */
	public static Lecture getLecture(String lectureID) {
		try {
			return fetchLecture(lectureID);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * get feedback of a specific lecture, if a lecturer checks for his lecture
	 * feedbacks updated status is reset to false
	 * 
	 * @param user
	 *            the user who checks for feedbacks
	 * @param lecture
	 *            the lecture interessted in
	 * @return the feedback
	 */
	public static List<Feedback> getFeedback(User user, Lecture lecture) {
		if(user==null || lecture==null)
			return new LinkedList<Feedback>();
		try {
			List<Feedback> feedback = CSVDatabase.fetchFeedback(lecture);
			if (user instanceof Lecturer)
				CSVDatabase.removeUpdatedFromLecture(lecture.getLectureID());
			return feedback;
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return new LinkedList<Feedback>();
	}
}
